package com.thinkbig.segment.tokenize;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import com.thinkbig.segment.resource.Resourcer;


public class Tokenizer {
    private static HashMap<Double, String> cache = new HashMap<Double, String>();
    public static final String SEPARATOR = "/ ";

    public static String tokenize(String query) {
        cache.clear();
        double cursorScore = MiscTokenize.DEFAULT_SCORE;
        tokenizeToRight(query);
        tokenizeToLeft(query);

        String rtn = "";
        for (double score : cache.keySet()) {
            if (cursorScore == 0 || cursorScore <= score) {
                rtn = cache.get(score);
                cursorScore = score;
            }
        }
        return rtn;
    }

    private static void tokenizeToRight(String s) {
        ArrayList<String> rtn = new ArrayList<String>();
        assert (s != null);
        HashMap<Integer, HashMap<String, Double>> DICT = Resourcer.DICT;
        Object[] keys = DICT.keySet().toArray();
        Arrays.sort(keys);
        int minWordLenth = (Integer) keys[0];

        ArrayList<Double> score = new ArrayList<Double>();
        while (s.length() > 0) {
            if (s.length() < minWordLenth) {
                for (int j = 0; j < s.length(); j++) {
                    String word = String.valueOf(s.charAt(j));
                    rtn.add(word);
                    score.add(MiscTokenize.DEFAULT_SCORE);
                }
                s = "";
            }
            for (int i = keys.length - 1; i >= 0; i--) {
                int wordLenth = 0;
                String subStr = null;
                try {
                    wordLenth = (Integer) keys[i];
                    if (wordLenth > s.length()) {
                        continue;
                    }
                    subStr = s.substring(0, wordLenth);
                    if (DICT.get(keys[i]).containsKey(subStr)) {
                        rtn.add(subStr);
                        score.add(DICT.get(keys[i]).get(subStr));
                        s = s.substring(wordLenth);
                        break;
                    } else if (i == 0 && subStr.length() != 0) {
                        rtn.add(String.valueOf(subStr.charAt(0)));
                        score.add(MiscTokenize.DEFAULT_SCORE);
                        s = s.substring(1);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
        cache.put(getScore(score), formatString(rtn, SEPARATOR));
        System.out.print(rtn);
        System.out.print(score);
        System.out.println(" averageScore:" + getScore(score));
    }

    private static void tokenizeToLeft(String s) {
        ArrayList<String> rtn = new ArrayList<String>();
        assert (s != null);
        HashMap<Integer, HashMap<String, Double>> DICT = Resourcer.DICT;
        Object[] keys = DICT.keySet().toArray();
        Arrays.sort(keys);
        int minWordLenth = (Integer) keys[0];

        ArrayList<Double> score = new ArrayList<Double>();
        while (s.length() > 0) {
            if (s.length() < minWordLenth) {
                for (int j = 0; j < s.length(); j++) {
                    String word = String.valueOf(s.charAt(j));
                    rtn.add(0, word);
                    score.add(0, MiscTokenize.DEFAULT_SCORE);
                }
                s = "";
            }
            for (int i = keys.length - 1; i >= 0; i--) {
                int wordLenth = 0;
                String subStr = null;
                try {
                    wordLenth = (Integer) keys[i];
                    if (wordLenth > s.length()) {
                        continue;
                    }
                    subStr = s.substring(s.length() - wordLenth);
                    if (DICT.get(keys[i]).containsKey(subStr)) {
                        rtn.add(0, subStr);
                        score.add(0, DICT.get(keys[i]).get(subStr));
                        s = s.substring(0, s.length() - wordLenth);
                        break;
                    } else if (i == 0 && subStr.length() != 0) {
                        rtn.add(0, String.valueOf(subStr.charAt(0)));
                        score.add(0, MiscTokenize.DEFAULT_SCORE);
                        s = s.substring(0, s.length() - 1);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
        cache.put(getScore(score), formatString(rtn, SEPARATOR));
        System.out.print(rtn);
        System.out.print(score);
        System.out.println(" averageScore:" + getScore(score));
    }

    private static double getScore(ArrayList<Double> scoreList) {
        if (scoreList.size() == 0) {
            return 0;
        } else {
            double total = 0;
            for (double d : scoreList) {
                total += d;
            }
            return total / scoreList.size();
        }
    }

    private static String formatString(ArrayList<String> stringList, String separator) {
        StringBuilder sb = new StringBuilder();
        for (String s : stringList) {
            sb.append(s);
            sb.append(separator);
        }
        return sb.toString().trim();
    }

}
